#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <pthread.h>
#include <unistd.h>

#define QUEUE_SIZE 10

typedef enum {
    PRIORITY_HIGH = 0,
    PRIORITY_MEDIUM = 1,
    PRIORITY_LOW = 2,
    PRIORITY_LEVELS
} Priority;

typedef struct {
    void *data;
    size_t size;
} Message;

typedef struct {
    Message buffer[QUEUE_SIZE];
    int head, tail, count;
} MsgQueue;

typedef struct {
    MsgQueue queues[PRIORITY_LEVELS];
    pthread_mutex_t mutex;
    pthread_cond_t not_empty;
    pthread_cond_t not_full;
} PriorityQueue;

// 初始化队列
void init_priority_queue(PriorityQueue *pq) {
    for (int i = 0; i < PRIORITY_LEVELS; ++i) {
        pq->queues[i].head = pq->queues[i].tail = pq->queues[i].count = 0;
    }
    pthread_mutex_init(&pq->mutex, NULL);
    pthread_cond_init(&pq->not_empty, NULL);
    pthread_cond_init(&pq->not_full, NULL);
}

// 入队
void enqueue(PriorityQueue *pq, void *data, size_t msg_size, Priority pri) {
    pthread_mutex_lock(&pq->mutex);
    MsgQueue *q = &pq->queues[pri];

    while (q->count == QUEUE_SIZE) {
        pthread_cond_wait(&pq->not_full, &pq->mutex);
    }

    Message *msg = &q->buffer[q->tail];
    if (msg_size) {
        free(msg->data); // 释放旧数据
    }
    msg->data = malloc(msg_size);
    memcpy(msg->data, data, msg_size);
    msg->size = msg_size;

    q->tail = (q->tail + 1) % QUEUE_SIZE;
    q->count++;

    pthread_cond_signal(&pq->not_empty);
    pthread_mutex_unlock(&pq->mutex);
}

// 出队
void* dequeue(PriorityQueue *pq, size_t *out_size) {
    pthread_mutex_lock(&pq->mutex);

    while (1) {
        for (int i = 0; i < PRIORITY_LEVELS; ++i) {
            MsgQueue *q = &pq->queues[i];
            if (q->count > 0) {
                Message msg = q->buffer[q->head];
                q->head = (q->head + 1) % QUEUE_SIZE;
                q->count--;

                pthread_cond_signal(&pq->not_full);
                pthread_mutex_unlock(&pq->mutex);

                if (out_size) *out_size = msg.size;
                return msg.data;
            }
        }
        pthread_cond_wait(&pq->not_empty, &pq->mutex);
    }
}

typedef struct {
    int id;
    char content[1024];
} Task;

void *producer_thread(void *arg) {
    PriorityQueue *pq = (PriorityQueue *)arg;

    for (int i = 0; i < 20; i++) {
        Task task;
        task.id = i;
        snprintf(task.content, sizeof(task.content), "Task #%d", i);

        Priority pri = rand() % PRIORITY_LEVELS;
        enqueue(pq, &task, sizeof(Task), pri);
        printf("Produced: id=%d, content=%s (priority=%d)\n", task.id, task.content, pri);

        usleep(100000); // 模拟延迟
    }

    return NULL;
}

void *consumer_thread(void *arg) {
    PriorityQueue *pq = (PriorityQueue *)arg;

    for (int i = 0; i < 20; i++) {
        size_t size;
        void *raw = dequeue(pq, &size);
        Task *task = (Task *)raw;

        printf("Consumed: id=%d, content=%s\n", task->id, task->content);
        free(task);

        usleep(150000); // 模拟处理延迟
    }

    return NULL;
}

// ========== 主函数 ==========

int main() {
    PriorityQueue pq;
    init_priority_queue(&pq);

    pthread_t producer, consumer;
    pthread_create(&producer, NULL, producer_thread, &pq);
    pthread_create(&consumer, NULL, consumer_thread, &pq);

    pthread_join(producer, NULL);
    pthread_join(consumer, NULL);

    return 0;
}
